package com.junjiao.util.java.security;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.ArrayList;
import java.util.List;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

/**
 * Description: 提供一些加解密的帮助方法<br>
 * Title: 新疆电信网上客服中心项目<br>
 * Copyright: Copyright (c) poson 版权<br>
 * 
 * @author Zhao Shanfu<br>
 * @version 1.0
 */
public class CipherHelper {

	// private static Logger logger = Logger.getLogger(CipherHelper.class);

	public static final int ENCRYPT_MODE = 1;// 3DES加密模式
	public static final int DECRYPT_MODE = 2;// 3DES解密模式

	/**
	 * 使用sun公司的jce安全算法
	 */
	static {
		// Security.addProvider(new com.sun.crypto.provider.SunJCE());
	}

	/**
	 * 调用JCE实现3DES算法
	 * 
	 * @param mode
	 *            加密还是解密
	 * @param inStr
	 *            要加密或者解密的数据
	 * @param key
	 *            24个字节的密钥
	 * @return 操作成功，则返回加密或者解密后的字符串；否则，返回null
	 */
	public static String tripleDES(int mode, String inStr, String key) {
		String outStr = null;
		byte[] inBytes = null;

		if (mode == ENCRYPT_MODE) {
			try {
				inBytes = inStr.getBytes("UTF-8");
				outStr = byte2hex(encode(inBytes, "DESede", key.getBytes()));
			} catch (UnsupportedEncodingException e) {

			}
		}
		if (mode == DECRYPT_MODE) {
			try {
				inBytes = hex2byte(inStr);
				outStr = new String(decode(inBytes, "DESede", key.getBytes()),
						"UTF-8");
			} catch (UnsupportedEncodingException e) {

			}
		}
		return outStr;
	}

	/**
	 * 消息摘要。使用algorithm摘要算法对inputStr进行消息摘要，支持MD5和SHA-1算法
	 * 
	 * @param inputBytes
	 * @param algorithm
	 * @return 成功，返回摘要字符串，否则，返回null
	 */
	public static String digest(byte[] inputBytes, String algorithm) {
		String outputStr = null;
		try {
			MessageDigest alg = MessageDigest.getInstance(algorithm);
			alg.update(inputBytes);
			byte[] digest = alg.digest();
			outputStr = byte2hex(digest);
		} catch (NoSuchAlgorithmException ex) {
			// logger.error("没有这种算法：" + algorithm);
			// Debugger.output(ex, logger);
		}
		return outputStr;
	}

	/**
	 * 分割字符串
	 * 
	 * @param input
	 *            要分割的字符串
	 * @param delimeter
	 *            分隔符
	 * @return
	 */
	public static String[] split(String input, String delimeter) {

		List temp = new ArrayList();
		int i = 0;
		do {
			int l = input.indexOf(delimeter);
			if (l < 0) {
				break;
			}
			String s = input.substring(0, l);
			temp.add(s);
			i = l + delimeter.length();
			input = input.substring(i);
		} while (input.indexOf(delimeter) >= 0);

		temp.add(input);
		Object[] temp1 = temp.toArray();
		String[] output = new String[temp1.length];
		System.arraycopy(temp1, 0, output, 0, temp1.length);
		return output;

	}

	/**
	 * 用algorithm算法和key对inputStr进行加密
	 * 
	 * @param input
	 *            要加密的字节数组
	 * @param algorithm
	 *            要使用的加密算法。支持DES,DESede,Blowfish,HmacMD5,HmacSHA1
	 * @param key
	 *            密钥
	 * @throws NoSuchPaddingException
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeyException
	 * @return 加密成功，返回加密后的字节数组，否则，返回null
	 */
	public static byte[] encode(byte[] input, String algorithm, byte[] key) {
		// Security.addProvider(new com.sun.crypto.provider.SunJCE());
		byte[] output = null;
		try {
			Cipher cipher = Cipher.getInstance(algorithm);
			cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, algorithm));
			output = cipher.doFinal(input);
		} catch (NoSuchAlgorithmException ex) {
			// logger.error("没有这种算法：" + algorithm);
			// Debugger.output(ex, logger);
		} catch (NoSuchPaddingException ex) {
			// Debugger.output(ex, logger);
		} catch (InvalidKeyException ex) {
			// logger.error("密钥错误");
			// Debugger.output(ex, logger);
		} catch (IllegalStateException ex) {
			// Debugger.output(ex, logger);
		} catch (IllegalBlockSizeException ex) {
			// Debugger.output(ex, logger);
		} catch (BadPaddingException ex) {
			// Debugger.output(ex, logger);
		}

		return output;
	}

	/**
	 * 用algorithm算法和key对inputStr进行解密
	 * 
	 * @param algorithm
	 *            要使用的解密算法。支持DES,DESede,Blowfish,HmacMD5,HmacSHA1
	 * @param inputStr
	 *            要解密的字节数组
	 * @param key
	 *            密钥
	 * @return 解密成功，返回解密后的字节数组，否则，返回null
	 */
	public static byte[] decode(byte[] input, String algorithm, byte[] key) {
		byte[] output = null;
		try {
			Cipher cipher = Cipher.getInstance(algorithm);
			cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, algorithm));
			output = cipher.doFinal(input);
		} catch (NoSuchAlgorithmException ex) {
			// logger.error("没有这种算法：" + algorithm);
			// Debugger.output(ex, logger);
		} catch (NoSuchPaddingException ex) {
			// Debugger.output(ex, logger);
		} catch (InvalidKeyException ex) {
			// logger.error("密钥错误");
			// Debugger.output(ex, logger);
		} catch (IllegalStateException ex) {
			// Debugger.output(ex, logger);
		} catch (IllegalBlockSizeException ex) {
			// Debugger.output(ex, logger);
		} catch (BadPaddingException ex) {
			// Debugger.output(ex, logger);
		}

		return output;
	}

	/**
	 * 二进制转十六进制字符串。每一个字节转为两位十六进制字符串。
	 * 
	 * @param b
	 * @return
	 */
	public static String byte2hex(byte[] b) {
		String hs = "";
		String stmp = "";
		for (int i = 0; i < b.length; i++) {
			stmp = Integer.toHexString(b[i] & 0XFF);
			if (stmp.length() == 1) {
				hs = hs + "0" + stmp;
			} else {
				hs = hs + stmp;
			}
		}
		return hs.toUpperCase();
	}

	/**
	 * 十六进制转字节数组
	 * 
	 * @param inputStr
	 * @return
	 */
	public static byte[] hex2byte(String hex) throws IllegalArgumentException {
		if (hex.length() % 2 != 0) {
			throw new IllegalArgumentException();
		}
		if (hex.startsWith("0x")) {
			hex = hex.substring(2);
		}
		char[] arr = hex.toCharArray();
		byte[] b = new byte[hex.length() / 2];
		for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {
			String swap = "" + arr[i++] + arr[i];
			int byteint = Integer.parseInt(swap, 16) & 0xFF;
			b[j] = new Integer(byteint).byteValue();
		}
		return b;
	}
}
